package persistencia;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import dominio.comida.BolaPacman;
import dominio.comida.BolaPacmanFactory;
import dominio.comida.Bolita;
import dominio.comida.Bolon;
import dominio.comida.IBolaPacmanFactory;
import dominio.comun.Posicion;
import dominio.laberinto.Casillero;
import dominio.laberinto.CasilleroFactory;
import dominio.laberinto.ICasillero;
import dominio.laberinto.ICasilleroFactory;
import dominio.laberinto.ICasilleroRepository;

public class XMLCasilleroRepository implements ICasilleroRepository {

	private Element elemRaiz;
	private List<ICasillero> casilleros;
	
	public void setElemRaiz(Element elemRaiz) {
		this.elemRaiz = elemRaiz;
	}

	@Override
	public void guardar(ICasillero casillero) {
		Element elemCasillero = DocumentHelper.createElement("nodo");
		
		Attribute id = DocumentHelper.createAttribute(elemCasillero, "id", casillero.getId());
		Attribute fila = DocumentHelper.createAttribute(elemCasillero, "fila", String.valueOf(casillero.getPosicion().getPosX()));
		Attribute columna = DocumentHelper.createAttribute(elemCasillero, "columna", String.valueOf(casillero.getPosicion().getPosY()));

		String strComida = "";
		if (casillero.getBola() != null) {
			if (casillero.getBola().getClass().getCanonicalName().contains("Bolita")) {
				strComida = "bolita";
			}
			if (casillero.getBola().getClass().getCanonicalName().contains("Bolon")) {
				strComida = "bolon";
			}
		}
		Attribute comida = DocumentHelper.createAttribute(elemCasillero, "contiene", strComida);
		
		String idIzquierda="";
		if (casillero.getCasilleroIzquierda()!=null) idIzquierda= casillero.getCasilleroIzquierda().getId();
		String idDerecha="";
		if (casillero.getCasilleroDerecha()!=null) idIzquierda= casillero.getCasilleroDerecha().getId();
		String idArriba="";
		if (casillero.getCasilleroArriba()!=null) idIzquierda= casillero.getCasilleroArriba().getId();
		String idAbajo="";
		if (casillero.getCasilleroAbajo()!=null) idIzquierda= casillero.getCasilleroAbajo().getId();
		
		Attribute izquierda = DocumentHelper.createAttribute(elemCasillero, "izquierda", idIzquierda);
		Attribute derecha = DocumentHelper.createAttribute(elemCasillero, "derecha", idDerecha);
		Attribute arriba = DocumentHelper.createAttribute(elemCasillero, "arriba", idArriba);
		Attribute abajo = DocumentHelper.createAttribute(elemCasillero, "abajo", idAbajo);
		
		elemCasillero.add(id);
		elemCasillero.add(fila);
		elemCasillero.add(columna);
		elemCasillero.add(comida);
		elemCasillero.add(izquierda);
		elemCasillero.add(derecha);
		elemCasillero.add(arriba);
		elemCasillero.add(abajo);
		
		this.elemRaiz.add(elemCasillero);
	}

	@SuppressWarnings("unchecked")
	@Override
	public ICasillero cargar(String id) {
		if (this.casilleros != null) {
			return this.getCasilleroById(id);
		}
		else {
			Iterator<Element> it = this.elemRaiz.elementIterator();
			while (it.hasNext()) {
				Element elem = it.next();
				String xmlId = elem.attributeValue("id");
				if (xmlId.equals(id)) {
					ICasillero casillero = this.cargar(elem, xmlId);
					this.setReferencias(casillero);
					return casillero;
				}
			}
		}
		return null;
	}

	@Override
	public List<ICasillero> listar() {
		this.casilleros = new ArrayList<ICasillero>();
		this.cargarContenido();
		this.cargarReferencias();
		return this.casilleros;
	}

	@SuppressWarnings("unchecked")
	private void cargarContenido() {
		Iterator<Element> it = this.elemRaiz.elementIterator();
		while (it.hasNext()) {
			Element elem = it.next();
			String id = elem.attributeValue("id");
			ICasillero casillero = cargar(elem, id);
			this.casilleros.add(casillero);
		}
	}

	private ICasillero cargar(Element elem, String id) {
		ICasilleroFactory casilleroFactory = new CasilleroFactory();
		IBolaPacmanFactory bolaPacmanFactory = new BolaPacmanFactory();
		
		int fila = Integer.parseInt(elem.attributeValue("fila"));
		int columna = Integer.parseInt(elem.attributeValue("columna"));
		
		BolaPacman bolita = null;
		String comida = elem.attributeValue("contiene");
		if (comida.equals("bolita")) {
			bolita = bolaPacmanFactory.crearBolita(fila, columna);
		}
		if (comida.equals("bolon")) {
			bolita = bolaPacmanFactory.crearBolon(fila, columna);
		}
		
		String izquierda = elem.attributeValue("izquierda");
		String derecha = elem.attributeValue("derecha");
		String arriba = elem.attributeValue("arriba");
		String abajo = elem.attributeValue("abajo");
		
		return casilleroFactory.crearCasillero(id, fila, columna, bolita, izquierda, derecha, arriba, abajo);
	}

	private void cargarReferencias() {
		for (ICasillero casillero : this.casilleros) {					
			this.setReferencias(casillero);
		}
	}	
	
	private void setReferencias(ICasillero casillero) {
		ICasillero casilleroIzquierda = this.getCasilleroById(casillero.getCasilleroIzquierda().getId());
		casillero.setCasilleroIzquierda(casilleroIzquierda);			
		
		ICasillero casilleroDerecha = this.getCasilleroById(casillero.getCasilleroDerecha().getId());
		casillero.setCasilleroDerecha(casilleroDerecha);			
		
		ICasillero casilleroArriba = this.getCasilleroById(casillero.getCasilleroArriba().getId());
		casillero.setCasilleroArriba(casilleroArriba);			
		
		ICasillero casilleroAbajo = this.getCasilleroById(casillero.getCasilleroAbajo().getId());
		casillero.setCasilleroAbajo(casilleroAbajo);		
	}

	private ICasillero getCasilleroById(String id) {
		for (ICasillero casillero : this.casilleros) {
			if (casillero.getId().equals(id)) {
				return casillero;
			}
		}
		return null;
	}

}
